package com.twt.recruit.controller;

import cn.hutool.core.convert.ConverterRegistry;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONConfig;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.twt.recruit.entity.*;
import com.twt.recruit.entity.vo.AnswerParam;
import com.twt.recruit.entity.vo.CategoryParam1;
import com.twt.recruit.entity.vo.ExcelApplication;
import com.twt.recruit.entity.vo.ExcelTime;
import com.twt.recruit.mapper.*;
import com.twt.recruit.service.ApplicationService;
import com.twt.recruit.service.ProjectService;
import com.twt.recruit.service.RecruitService;
import com.twt.recruit.utils.JwtTokenUtils;
import com.twt.recruit.utils.response.CommonEnum;
import com.twt.recruit.utils.response.ResultBody;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

@RestController
@RequestMapping("/v1")
public class RecruitController {

    private final static Logger logger = LoggerFactory.getLogger(RecruitController.class);

    @Resource
    ApplicationMapper applicationMapper;

    @Resource
    ApplicationInfoMapper applicationInfoMapper;
    @Resource
    AnswerMapper answerMapper;

    @Resource
    UserMapper userMapper;

    @Resource
    GroupMapper groupMapper;

    @Resource
    TimeMapper timeMapper;

    @Resource
    ApplicationService applicationService;

    @Resource
    CategoryMapper categoryMapper;

    @Resource
    CategoryInfoMapper categoryInfoMapper;

    @Resource
    TimeHandMapper timeHandMapper;

    @Resource
    CommentMapper commentMapper;

    @Resource
    ProjectMapper projectMapper;

    @Resource
    QuestionMapper questionMapper;

    @Resource
    ProjectService projectService;

    @Resource
    RecruitService recruitService;

    @Value("${times}")
    String TIME;



    @PostMapping("/user/application")
    @Operation(summary = "添加报名信息")
    public ResultBody addApplication(@RequestParam String applicationUid,
                                     @RequestParam String applicationName,
                                     @RequestParam Integer projectId,
                                     @RequestParam String applicationContact,
                                     @RequestParam String applicationCampus,
                                     @RequestParam List<Integer> wantedGroupIds,
                                     @RequestParam String answers,
                                     @Parameter(description = "时间段9:00-12:00,14:00-21:00英文逗号分割") @RequestParam String dateTimes) {
        try {
            if (wantedGroupIds.isEmpty()){
                return ResultBody.error("未选择组别");
            }

            if (dateTimes == null || dateTimes.isEmpty()){
                return ResultBody.error("未选择面试时间");
            }

//            Application application = new Application(null, applicationUid, applicationName, applicationContact, applicationCampus, projectId, null, null);
            Application application = Application.builder()
                    .applicationUid(applicationUid)
                    .applicationName(applicationName)
                    .applicationContact(applicationContact)
                    .applicationCampus(applicationCampus)
                    .projectId(projectId)
                    .build();
            LambdaQueryWrapper<Application> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Application::getProjectId, projectId);
            queryWrapper.eq(Application::getApplicationUid, applicationUid);
            if (!applicationMapper.selectList(queryWrapper).isEmpty()){
                return ResultBody.error(CommonEnum.APPLICATION_REPEAT);
            }

            // 判断时间段是否在规定范围内
            //            for (String time : times) {
//                List<String> t = Arrays.asList(TIME.split(","));
//                if (!t.contains(time)){
//                    return ResultBody.error(CommonEnum.TIME_ERROR);
//                }
//            }

            String[] dateTime = dateTimes.split(",");
            for (String str : dateTime){
                String[] dateAndTimes = str.split(" ");
                List<String> t = Arrays.asList(TIME.split(","));
                for (int i = 1; i < dateAndTimes.length; i++){
                    System.out.println(dateAndTimes[i]);
                    if (!t.contains(dateAndTimes[i])){
                        return ResultBody.error(CommonEnum.TIME_ERROR);
                    }
                }
            }


            //常规问题
//            JSONUtil.parseArray(answers).forEach(a -> {
//                JSONObject jsonAnswer = JSONUtil.parseObj(a);
//                Integer groupId = jsonAnswer.getInt("groupId");
//                for (AnswerParam quest : jsonAnswer.getBeanList("quest", AnswerParam.class)) {
//                    Answer answer = new Answer(null, applicationUid, projectId, groupId, quest.getQuestionId(), quest.getQuestionAnswer().toString());
//                    answerMapper.insert(answer);
//                }
//            });

            for (Object a : JSONUtil.parseArray(answers)){
                JSONObject jsonAnswer = JSONUtil.parseObj(a);
                Integer groupId = jsonAnswer.getInt("groupId");

                //判断必填问题是否为空
                for (AnswerParam quest : jsonAnswer.getBeanList("quest", AnswerParam.class)) {
                    Answer answer = new Answer(null, applicationUid, projectId, groupId, quest.getQuestionId(), quest.getQuestionAnswer().toString());
                    Question question = questionMapper.selectById(quest.getQuestionId());
                    if (question != null && wantedGroupIds.contains(question.getGroupId())){
                        String answerContent = answer.getAnswerContent();
                        String questionContent = question.getQuestionContent();
                        if (questionContent.contains("\"required\":true")){
                            answerContent = answerContent.replace('[', ' ');
                            answerContent = answerContent.replace(']', ' ');
                            answerContent = answerContent.trim();
                            if (answerContent == null || answerContent.isEmpty() || answerContent.isBlank()){
                                return ResultBody.error("未完成填写");
                            }
                        }
                    }
                }

                for (AnswerParam quest : jsonAnswer.getBeanList("quest", AnswerParam.class)) {
                    Answer answer = new Answer(null, applicationUid, projectId, groupId, quest.getQuestionId(), quest.getQuestionAnswer().toString());
                    answerMapper.insert(answer);
                }
            }

            applicationMapper.insert(application);


            if (userMapper.selectById(applicationUid)==null){
                User user = new User();
                user.setUid(applicationUid);
                user.setName(applicationName);
                user.setTelephone(applicationContact);
                user.setCampus(applicationCampus);
                userMapper.insert(user);
            }
            Integer applicationId = application.getApplicationId();
            for (int i = 0; i < wantedGroupIds.size(); i++) {
                applicationInfoMapper.insert(new ApplicationInfo(null, applicationId, projectId, wantedGroupIds.get(i), (byte) 0, i + 1));
            }

            //面试时间
//            for (String time : times) {
//                timeMapper.insert(new Time(null, projectId, applicationId, time));
//            }
            for (String str : dateTime){
                String[] dateAndTimes = str.split(" ");
                String date = dateAndTimes[0];
                for (int i = 1; i < dateAndTimes.length; i++){
                    String time = dateAndTimes[i];
                    timeMapper.insert(new Time(null, projectId, applicationId, date, time));
                }
            }

            return ResultBody.success("报名成功");
        } catch (Exception e) {
            logger.error("报名失败", e);
            return ResultBody.error("报名失败");
        }

    }

    @Operation(summary = "获取面试信息")
    @GetMapping("/staff/applications/brief")
    public ResultBody getApplication(@RequestParam(required = false) String uid,
                                     @RequestParam(required = false) String name,
                                     @RequestParam Integer projectId,
                                     @RequestHeader(JwtTokenUtils.TOKEN_HEADER) String token){
        if (!projectService.isClubProject(projectId, JwtTokenUtils.getClubHttp(token))){
            return ResultBody.error(CommonEnum.PROJECT_VIRES);
        }
        try {
            LambdaQueryWrapper<Application> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Application::getProjectId, projectId);

            if (name!=null && !name.isEmpty()){
                queryWrapper.like(Application::getApplicationName, name);
            }
            if (uid!=null && !uid.isEmpty()){
                queryWrapper.like(Application::getApplicationUid, uid);
            }
            JSONArray re = new JSONArray();
            for (Application application : applicationMapper.selectList(queryWrapper)) {
                JSONObject t = new JSONObject();
                t.putOpt("uid", application.getApplicationUid());
                t.putOpt("name", application.getApplicationName());
                Integer applicationId = application.getApplicationId();

                HashMap<String, Object> p2 = new HashMap<>();
                p2.put("application_id", applicationId);
                JSONArray groups = new JSONArray();
                //组别及其问题答案
                for (ApplicationInfo applicationInfo : applicationInfoMapper.selectByMap(p2)){
                    JSONObject g = new JSONObject();
                    Integer groupId = applicationInfo.getGroupId();
                    g.putOpt("groupId", groupId);
                    g.putOpt("groupName", groupMapper.selectById(groupId).getGroupName());
                    g.putOpt("status", applicationInfo.getStatus());
                    g.putOpt("categories", applicationMapper.listCategoryNamesByApplicationId(applicationId, groupId).toString().replace("[", "").replace("]", ""));
                    groups.add(g);
                }
                t.putOpt("groups", groups);
                re.add(t);
            }
            return ResultBody.success(re);
        }catch ( Exception e){
            logger.error("获取报名信息失败", e);
            return ResultBody.error("获取报名信息失败");
        }
    }



    @Operation(summary = "获取个人面试信息")
    @GetMapping("/user/applications")
    public ResultBody getMyApplications(@RequestHeader(JwtTokenUtils.TOKEN_HEADER) String token){
        try {
            String uid = JwtTokenUtils.getUserNumberHttp(token);
            JSONArray re = new JSONArray();
            for (Application application : applicationMapper.listApplicationsByUid(uid)) {
                re.add(applicationService.dealApplication(application));
            }
            return ResultBody.success(re);
        }catch ( Exception e){
            logger.error("获取报名信息失败", e);
            return ResultBody.error("获取报名信息失败");
        }

    }


    @Operation(summary = "获取分组信息")
    @GetMapping("/staff/category/detail")
    public ResultBody getCategoryDetail(@RequestParam Integer projectId,
                                        @Parameter(description = "只传projectId拿到全部下的分类，传groupId拿到对应组别下的分类") @RequestParam(required = false) Integer groupId,
                                        @RequestHeader(JwtTokenUtils.TOKEN_HEADER) String token){
        if (!projectService.isClubProject(projectId, JwtTokenUtils.getClubHttp(token))){
            return ResultBody.error(CommonEnum.PROJECT_VIRES);
        }
        try {
            if (groupId==null){
                //不传组别，直接拿全部
                String[] times = TIME.split(",");
                List<JSONArray> re = new ArrayList<>();
                for (String time : times) {
                    JSONArray a = new JSONArray();
                    for (int i = 1; i < 4; i++) {
                        LambdaQueryWrapper<TimeHand> queryWrapper = new LambdaQueryWrapper<>();
                        queryWrapper.eq(TimeHand::getProjectId, projectId);
                        queryWrapper.eq(TimeHand::getTimeSection, time);
                        queryWrapper.eq(TimeHand::getDay, i);
                        List<TimeHand> timeHands =  timeHandMapper.selectList(queryWrapper);
                        JSONArray applications = new JSONArray();
                        for (TimeHand timeHand : timeHands) {
                            Integer applicationId = timeHand.getApplicationId();
                            applications.add(recruitService.dealCategory(applicationId));
                        }
                        JSONObject tmp = new JSONObject();
                        tmp.putOpt("count", timeHands.size());
                        tmp.putOpt("applications", applications);
                        a.add(tmp);
                    }
                    re.add(a);
                }
                return ResultBody.success(re);
            }

            //组别-默认
            JSONObject group = new JSONObject();
            JSONArray groupAllCategories = new JSONArray();
            group.putOpt("groupId", groupId);
            group.putOpt("groupName", groupMapper.selectById(groupId).getGroupName());
            CategoryParam1 defaultCategory = new CategoryParam1(-1, "全部", 0);
            List<CategoryParam1> categoryParam1List = new ArrayList<>(List.of(defaultCategory));
            categoryParam1List.addAll(categoryMapper.getCategoryIdsByProjectIdAndGroupId(projectId, groupId));
            System.out.println(categoryParam1List);
            for (CategoryParam1 categoryParam1 : categoryParam1List) {
                JSONObject category = JSONUtil.parseObj(categoryParam1);
                JSONArray content = new JSONArray();
                for (int i = 0; i < 3; i++) {
                    JSONObject c = new JSONObject();
                    List<Integer> applicationIds = categoryParam1.getCategoryId()!=-1?categoryInfoMapper.getApplicationIdsByCategoryId(categoryParam1.getCategoryId(), i):applicationInfoMapper.getApplicationIdsByProjectIdAndGroupId(projectId, groupId, i);
                    System.out.println(applicationIds);
                    JSONArray applications = new JSONArray();
                    for (Integer applicationId : applicationIds) {
                        applications.add(recruitService.dealCategory(applicationId));
                    }
                    c.putOpt("status", i);
                    c.putOpt("applications", applications);
                    c.putOpt("count", applicationIds.size());
                    content.add(c);
                }
                category.putOpt("content", content);
                groupAllCategories.add(category);

            }
            group.putOpt("categories", groupAllCategories);
            return ResultBody.success(group);
        }catch (Exception e){
            logger.error("获取分组信息失败", e);
            return ResultBody.error("获取分组信息失败");
        }
    }

    @Operation(summary = "批量获取面试申请")
    @GetMapping("/staff/applications")
    public ResultBody listApplications(@RequestParam List<Integer> applicationIds){
        try {
            JSONArray re = new JSONArray();
            for (Integer applicationId : applicationIds) {
                re.add(applicationService.getSingleApplication(applicationId));
            }
            return ResultBody.success(re);
        }catch (Exception e){
            logger.error("批量获取面试申请失败", e);
            return ResultBody.error("批量获取面试申请失败");
        }

    }



    @PostMapping("/inter/category/copy")
    @Operation(summary = "分组复制")
    public ResultBody copyCategory(@RequestParam Integer categoryId,
                                   @RequestParam List<Integer> applicationId){
        try {
            for (Integer i : applicationId) {
                LambdaQueryWrapper<CategoryInfo> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(CategoryInfo::getCategoryId, categoryId);
                queryWrapper.eq(CategoryInfo::getApplicationId, i);
                if (categoryInfoMapper.selectList(queryWrapper).isEmpty()){
                    CategoryInfo categoryInfo = new CategoryInfo(null, categoryId, i);
                    categoryInfoMapper.insert(categoryInfo);
                }
            }
            return ResultBody.success("复制成功");

        }catch (Exception e){
            logger.error("复制失败", e);
            return ResultBody.error("复制失败");
        }
    }

    @PostMapping("/inter/category/cut")
    @Operation(summary = "分组移动")
    public ResultBody cutCategory(@RequestParam Integer oldCategoryId,
                                  @RequestParam Integer newCategoryId,
                                  @RequestParam List<Integer> applicationId){
        try {
            for (Integer i : applicationId) {
                LambdaUpdateWrapper<CategoryInfo> wrapper = new LambdaUpdateWrapper<>();
                wrapper.eq(CategoryInfo::getCategoryId, oldCategoryId);
                wrapper.eq(CategoryInfo::getApplicationId, i);
                wrapper.set(CategoryInfo::getCategoryId, newCategoryId);
                categoryInfoMapper.update(wrapper);
            }
            return ResultBody.success("移动成功");
        }catch (Exception e){
            logger.error("移动失败", e);
            return ResultBody.error("移动失败");
        }
    }



    @PostMapping("/inter/category/new")
    @Operation(summary = "新建分组")
    public ResultBody addCategory(@RequestParam Integer groupId,
                                  @RequestParam Integer projectId,
                                  @RequestParam String categoryName,
                                  @RequestHeader(JwtTokenUtils.TOKEN_HEADER) String token){
        try {
            if (!projectService.isClubProject(projectId, JwtTokenUtils.getClubHttp(token))){
                return ResultBody.error(CommonEnum.PROJECT_VIRES);
            }
            Category category = new Category(null, projectId, groupId, categoryName, 0);
            categoryMapper.insert(category);
            return ResultBody.success(category);
        }catch (Exception e){
            logger.error("新建失败", e);
            return ResultBody.error("新建失败");
        }
    }



    @PostMapping("/inter/time")
    @Operation(summary = "自动分组")
    public ResultBody autoTime(@RequestParam(defaultValue = "3") Integer day,
                               @RequestParam Integer projectId,
                               @RequestHeader(JwtTokenUtils.TOKEN_HEADER) String token){
        if (!projectService.isClubProject(projectId, JwtTokenUtils.getClubHttp(token))){
            return ResultBody.error(CommonEnum.PROJECT_VIRES);
        }
        try {
            recruitService.interviewSchedule(day, projectId);
            return ResultBody.success(recruitService.getAuto(projectId));
        }catch (Exception e){
            logger.error("自动分组失败", e);
            return ResultBody.error("自动分组失败");
        }
    }

    @GetMapping("/inter/time")
    @Operation(summary = "获取自动分组")
    public ResultBody getAutoTime(@RequestParam Integer projectId,
                                  @RequestHeader(JwtTokenUtils.TOKEN_HEADER) String token){
        if (!projectService.isClubProject(projectId, JwtTokenUtils.getClubHttp(token))){
            return ResultBody.error(CommonEnum.PROJECT_VIRES);
        }
        try {

            return ResultBody.success(recruitService.getAuto(projectId));
        }catch (Exception e){
            logger.error("自动分组失败", e);
            return ResultBody.error("自动分组失败");
        }
    }

    @PostMapping("/inter/day")
    @Operation(summary = "设置具体开始日期")
    public ResultBody setDay(@RequestParam long startTime,
                             @RequestParam Integer projectId,
                             @RequestHeader(JwtTokenUtils.TOKEN_HEADER) String token){
        if (!projectService.isClubProject(projectId, JwtTokenUtils.getClubHttp(token))){
            return ResultBody.error(CommonEnum.PROJECT_VIRES);
        }
        Timestamp s = new Timestamp(startTime);
        LambdaUpdateWrapper<Project> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Project::getProjectId, projectId);
        updateWrapper.set(Project::getStartTime, s);
        return ResultBody.success(projectMapper.update(updateWrapper));
    }

    @PostMapping("/inter/time/hand")
    @Operation(summary = "手动调整面试时间")
    public ResultBody updateTimeByHand(@RequestParam Integer applicationId,
                                       @RequestParam Integer projectId,
                                       @RequestParam(defaultValue = "1") Integer day,
                                       @RequestParam String timeSection,
                                       @RequestHeader(JwtTokenUtils.TOKEN_HEADER) String token){
        if (!projectService.isClubProject(projectId, JwtTokenUtils.getClubHttp(token))){
            return ResultBody.error(CommonEnum.PROJECT_VIRES);
        }
        try {
            TimeHand timeHand = new TimeHand(applicationId, projectId, day, timeSection, (byte) 1);
            if (timeHandMapper.selectById(applicationId)==null){
                timeHandMapper.insert(timeHand);
            }else {
                timeHandMapper.updateById(timeHand);
            }
            return ResultBody.success();
        }catch (Exception e){
            logger.error("手动调整时间失败", e);
            return ResultBody.error("手动调整时间失败");
        }
    }



    @Operation(summary = "导出面试信息")
    @GetMapping("/inter/export")
    public void exportApplication(@RequestParam List<Integer> applicationIds,
                                        HttpServletResponse response) throws IOException {
        try {
            ArrayList<ExcelApplication> applicationParams = new ArrayList<>();
            for (Integer applicationId : applicationIds) {
                Application application = applicationMapper.selectById(applicationId);
                User user = userMapper.selectById(application.getApplicationUid());
                ConverterRegistry converterRegistry = ConverterRegistry.getInstance();
                ExcelApplication p = converterRegistry.convert(ExcelApplication.class, user);
                p.setGroup(applicationMapper.listGroupNamesByApplicationId(applicationId).toString());
                p.setTime(applicationMapper.listTimesByApplicationId(applicationId).toString());
                TimeHand timeHand = timeHandMapper.selectById(applicationId);
                p.setDay(timeHand.getDay());
                p.setTimeFinal(timeHand.getTimeSection());
                applicationParams.add(p);
            }

            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            response.setHeader("Content-disposition", "attachment;filename=response.xlsx");
            EasyExcel.write(response.getOutputStream(), ExcelApplication.class).autoCloseStream(Boolean.FALSE).sheet("模板")
                    .doWrite(applicationParams);
        }catch (Exception e){
            logger.error("导出面试信息失败", e);
            response.setCharacterEncoding("UTF-8");
            response.setStatus(HttpServletResponse.SC_OK);
            response.setContentType("application/json; charset=utf-8");
            ResultBody resultBody = new ResultBody(CommonEnum.APPLICATION_EXPORT);
            response.getWriter().write(JSONUtil.toJsonStr(resultBody, JSONConfig.create().setIgnoreNullValue(false)));

        }

    }

    @Operation(summary = "导出面试时间")
    @GetMapping("/inter/export/time")
    public void exportProjectTime(@RequestParam Integer projectId,
                                  @RequestHeader(JwtTokenUtils.TOKEN_HEADER) String token,
                                  HttpServletResponse response) throws IOException {
        if (!projectService.isClubProject(projectId, JwtTokenUtils.getClubHttp(token))){
            response.setCharacterEncoding("UTF-8");
            response.setStatus(HttpServletResponse.SC_OK);
            response.setContentType("application/json; charset=utf-8");
            ResultBody resultBody = new ResultBody(CommonEnum.PROJECT_VIRES);
            response.getWriter().write(JSONUtil.toJsonStr(resultBody, JSONConfig.create().setIgnoreNullValue(false)));
            return;
        }
        try {
            ArrayList<ExcelTime> applicationParams = new ArrayList<>();
            LambdaQueryWrapper<TimeHand> timeHandLambdaQueryWrapper = new LambdaQueryWrapper<>();
            timeHandLambdaQueryWrapper.eq(TimeHand::getProjectId, projectId);
            for (TimeHand timeHand : timeHandMapper.selectList(timeHandLambdaQueryWrapper)) {
                ExcelTime excelTime = new ExcelTime();
                excelTime.setDay(timeHand.getDay());
                excelTime.setTimeSection(timeHand.getTimeSection());
                excelTime.setUid(applicationMapper.selectById(timeHand.getApplicationId()).getApplicationUid());
                applicationParams.add(excelTime);

            }
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            response.setHeader("Content-disposition", "attachment;filename=response.xlsx");
            EasyExcel.write(response.getOutputStream(), ExcelTime.class).autoCloseStream(Boolean.FALSE).sheet("模板")
                    .doWrite(applicationParams);
        }catch (Exception e){
            logger.error("导出面试时间失败", e);
            response.setCharacterEncoding("UTF-8");
            response.setStatus(HttpServletResponse.SC_OK);
            response.setContentType("application/json; charset=utf-8");
            ResultBody resultBody = new ResultBody(CommonEnum.TIME_EXPORT);
            response.getWriter().write(JSONUtil.toJsonStr(resultBody, JSONConfig.create().setIgnoreNullValue(false)));

        }

    }

    @PostMapping("/inter/application/comment")
    @Operation(summary = "评论")
    public ResultBody addComment(@RequestHeader(JwtTokenUtils.TOKEN_HEADER) String token,
                                 @RequestParam Integer applicationId,
                                 @RequestParam String commentContent){

        String uid = JwtTokenUtils.getUserNumberHttp(token);
        if (uid.isEmpty()){
            return ResultBody.error(CommonEnum.COMMENT_ERROR);
        }
        ApplicationComment applicationComment = new ApplicationComment(null, applicationId, uid, commentContent, null, null);
        commentMapper.insert(applicationComment);
        return ResultBody.success(commentMapper.selectById(applicationComment.getId()));
    }


}
